package poker;

import java.util.Random;

import exception.HandSizeEx;
import exception.InvalidCardEx;
import exception.InvalidPhaseEx;
import exception.PlayerActionEx;
import exception.PlayerCountEx;
import exception.PlayerTypeEx;
import view.PokerView;

public class Table {
	private Player[] thePlayers;
	private Deck theDeck;
	private boolean hasAllIn;
	private boolean dcgeddon;
	private boolean fullCircle;
	private int fee;
	private int bet;
	private int curPlayer;
	private int opener;
	private Phase phase;
	private PokerView pv;
	
	public Table(final PlayerInfo[] players, final int fee, final int tokens) 
			throws IllegalArgumentException, InvalidCardEx, HandSizeEx {
		if (players.length > 4 || players.length < 2) {
			throw new IllegalArgumentException("Niepoprawna liczba graczy!");
		}
		if(fee < 1 || tokens < 1) {
			throw new IllegalArgumentException("Stawka i liczba zetonow musza byc wieksze od zera!");
		}
		if(fee > tokens) {
			throw new IllegalArgumentException("Stawka musi byc mniejsza od liczby zetonow!");
		}
		for(int i=0; i < players.length; i++) {
			if(players[i].name.equals("")) {
				throw new IllegalArgumentException("Puste imię!");
			}
		}
		thePlayers = new Player[players.length];
		int i;
		for(i = 0; i < players.length; i++) {
			if(!players[i].isBot) { 
				thePlayers[i] = new Human(players[i].name, tokens);
			} else {
				thePlayers[i] = new Bot(players[i].name, tokens);
			}
		}
		
		this.fee = fee;
		phase = Phase.FirstAuction;
		theDeck = new Deck();
		curPlayer = new Random().nextInt(players.length);
		opener = curPlayer;
		hasAllIn = false;
		dcgeddon = false;
		fullCircle = false;

		for(i=0; i<thePlayers.length; i++) {
			for(int j=0; j<5; j++) {
				thePlayers[i].receiveCard(theDeck.takeCard());
			}
		}
	}
	
	public Table(Player[] thePlayers, final int fee) throws InvalidCardEx {
		this.thePlayers = thePlayers;
		this.fee = fee;
		phase = Phase.FirstAuction;
		theDeck = new Deck();
		curPlayer = 0;
		hasAllIn = false;
		dcgeddon = false;
		fullCircle = false;
	}
	
	public void setView(PokerView pv) {
		this.pv = pv;
	}
	
	public void forceDataFeed() {
		sendData();
	}
	
	public Phase getPhase() {
		return phase;
	}
	
	public int getPlayerCount() {
		return thePlayers.length;
	}
	
	public void handleBot() throws PlayerTypeEx, InvalidPhaseEx, HandSizeEx, InvalidCardEx {
		if(!thePlayers[curPlayer].isBot()) throw new PlayerTypeEx("Not a bot!");
		if(phase == Phase.AnnounceWinner) throw new InvalidPhaseEx();
		PlayerAction botAction = thePlayers[curPlayer].takeTurn(phase, bet, hasAllIn);
		if(phase == Phase.FirstAuction || phase == Phase.SecondAuction) {
			if(botAction == PlayerAction.BET) {
				bet = fee;
				thePlayers[curPlayer].setBet(fee);
			} else if(botAction == PlayerAction.RAISE) {
				bet = thePlayers[curPlayer].getBet();
			} else if(botAction == PlayerAction.ALLIN) {
				hasAllIn = true;
			} else if(botAction == PlayerAction.FOLD) {
				handleFolding(curPlayer);
				return;
			}
		} else {
			int cards = 5 - thePlayers[curPlayer].getHandSize();
			for(int i=0; i<cards; i++) {
				thePlayers[curPlayer].receiveCard(theDeck.takeCard());
			}
		}
		incCurPlayer();
	}
	
	// dla licytacji
	public void advance(final PlayerAction action, final int amount) throws InvalidPhaseEx, PlayerActionEx {
		if(phase == Phase.Exchange || phase == Phase.AnnounceWinner) throw new InvalidPhaseEx();
		if(thePlayers[curPlayer].getTokens() < amount ) {
			sendMessage("Masz za mało żetonów!");
			throw new PlayerActionEx("Brak żetonów");
		}
		if(hasAllIn == true && action != PlayerAction.ALLIN && action != PlayerAction.FOLD) { 
			sendMessage("Musisz wejść all-in!");
			throw new PlayerActionEx("Konieczne all-in");
		}
		if(bet == 0 && action != PlayerAction.BET && action != PlayerAction.CHECK && action != PlayerAction.FOLD) { 
			sendMessage("Nie ma jeszcze pierwszej stawki!");
			throw new PlayerActionEx("Nie ma stawki");
		}
		if(action == PlayerAction.FOLD) {
			thePlayers[curPlayer].fold();
			handleFolding(curPlayer);
			return;
		} else if(action == PlayerAction.BET) {
			if(bet != 0) {
				sendMessage("Już jest pierwsza stawka!");
				throw new PlayerActionEx("Już jest stawka");
			}
			bet = fee;
			thePlayers[curPlayer].setBet(fee);
		} else if(action == PlayerAction.CHECK) {
			if(bet != 0) { 
				sendMessage("Nie możesz już czekać!");
				throw new PlayerActionEx("Nie można czekać po stawce");
			}
		} else if(action == PlayerAction.CALL) {
			if (bet > thePlayers[curPlayer].getTokens()) {
				sendMessage("Stawka jest za wysoka!");
				throw new PlayerActionEx("Brak żetonów żeby wyrównać");
			}
			thePlayers[curPlayer].setBet(bet);
		} else if(action == PlayerAction.RAISE) {
			if(amount < 0) {
				sendMessage("Wprowadź poprawną stawkę!");
				throw new PlayerActionEx("Stawka ujemna");
			}
			if(amount <= bet) {
				sendMessage("Musisz postawić więcej!");
				throw new PlayerActionEx("Za mało żeby przebić");
			}
			bet = amount;
			thePlayers[curPlayer].setBet(amount);
		} else if(action == PlayerAction.ALLIN) {
			if(thePlayers[curPlayer].getTokens() >= bet) {
				sendMessage("Nie możesz wejść all-in, jeżeli możesz zrównać stawkę!");
				throw new PlayerActionEx("Za dużo żetonów na all-in");
			}
			hasAllIn = true;
			thePlayers[curPlayer].allIn();
			if(thePlayers[curPlayer].getTokens() > bet) {
				bet = thePlayers[curPlayer].getTokens();
			}
			thePlayers[curPlayer].setBet(thePlayers[curPlayer].getTokens());
		}
		incCurPlayer();
		
		return;
	}
	
	// dla wymiany kart
	public void advance(int cards[]) throws InvalidPhaseEx, InvalidCardEx, HandSizeEx, IllegalArgumentException {
		if(phase != Phase.Exchange) throw new InvalidPhaseEx();
		int[] translation = new int[4];
		int transCount = 0; 
		for(int i=0; i<cards.length; i++) {
			if(cards[i] != 0) {
				if(transCount < 4) {
					translation[transCount] = cards[i];
					transCount++;
				} else {
					sendMessage("Możesz wymienić tylko pięć kart!");
					throw new IllegalArgumentException("Za dużo kart!");
				}
			}
		}
		thePlayers[curPlayer].exchangeCards(translation);
		int count = 5 - thePlayers[curPlayer].getHandSize();
		for(int i=0; i<count; i++) {
			thePlayers[curPlayer].receiveCard(theDeck.takeCard());
		}
		incCurPlayer();
	}
	
	public void showResult() throws InvalidPhaseEx {
		if(phase != Phase.AnnounceWinner) throw new InvalidPhaseEx();
		int[][] score = new int[thePlayers.length][6];
		int[] players = new int[thePlayers.length];
		int[][] cards = new int[thePlayers.length][5];
		int[][] cardsToSend = new int[thePlayers.length][5];
		for (int i = 0; i < thePlayers.length; i++) {
			if(!thePlayers[i].hasFolded()) {
				players[i] = i;
			} else {
				players[i] = -1;
			}
			thePlayers[i].reportCards(cards[i]);
			thePlayers[i].reportCards(cardsToSend[i]);
			analyzeCards(score[i], cards[i]);
		}
		
		findWinner(score, players);
		int winnerCount = 0;
		int playCount = thePlayers.length;
		for (int i = 0; i < thePlayers.length; i++) {
			if (players[i] != -1) {
				winnerCount++;
				thePlayers[i].win();
			}
			if(thePlayers[i].hasDCed()) {
				playCount--;
			}
		}
		payUp(winnerCount, players, thePlayers);
		for(int i=0; i<thePlayers.length; i++) {
			if(thePlayers[i].getTokens() < fee) {
				thePlayers[i].dc();
				thePlayers[i].bankrupt();
				if(--playCount < 2) {
					dcgeddon = true;
				}
				
			}
		}
		WinInfo[] wInfo = new WinInfo[thePlayers.length]; 
		for(int i=0; i<thePlayers.length; i++) {
			wInfo[i] = new WinInfo();
			wInfo[i].name = thePlayers[i].getName();
			if(thePlayers[i].isBroken()) {
				wInfo[i].status = "(Bankrupt)";
			} else if(thePlayers[i].hasDCed()) {
				wInfo[i].status = "(Disconnected)";
			}  else if(thePlayers[i].hasFolded()) {
				wInfo[i].status = "(Folded)"; 
			}
			switch (score[i][0]) {
			case 9:
				wInfo[i].hand = "Poker"; 
				break;
			case 8:
				wInfo[i].hand = "Czwórka";
				break;
			case 7:
				wInfo[i].hand = "Full";
				break;
			case 6:
				wInfo[i].hand = "Kolor";
				break;
			case 5:
				wInfo[i].hand = "Strit";
				break;
			case 4:
				wInfo[i].hand = "Trójka";
				break;
			case 3:
				wInfo[i].hand = "Dwie pary";
				break;
			case 2:
				wInfo[i].hand = "Para";
				break;
			case 1:
				wInfo[i].hand = "Karta";
				break;
			default:
				break;
			}
			wInfo[i].tokens = thePlayers[i].getTokens();
			wInfo[i].winCount = thePlayers[i].getWins();
		}
		StringBuilder winString = new StringBuilder();
		if (winnerCount == 1) {
			winString.append("Wygrał ");
			for (int i = 0; i < thePlayers.length; i++) {
				if (players[i] != -1) {
					winString.append(thePlayers[i].getName());
				}
			}
			winString.append("!");
		} else if(winnerCount == 0) {
			winString.append("Wszyscy przegrali!");
		} else {
			winString.append("Zremisowali gracze");
			for (int i = 0; i < thePlayers.length; i++) {
				if (players[i] != -1) {
					winString.append(" " + thePlayers[i].getName());
				}
			}
			winString.append("!");
		}
		sendResults(cardsToSend, wInfo, winString.toString());
	}
	
	public void disconnectPlayer(int playerNr) throws PlayerCountEx, InvalidPhaseEx {
		playerNr--;
		if(playerNr >= thePlayers.length || playerNr < 0) throw new PlayerCountEx();
		thePlayers[playerNr].fold();
		thePlayers[playerNr].dc();
		int playCount = 0;
		for(int i=0; i<thePlayers.length; i++) {
			if(!thePlayers[i].hasDCed()) playCount++;
		}
		if(playCount < 2) {
			dcgeddon = true;
			phase = Phase.AnnounceWinner;
			sendPhaseChange();
			return;
		}
		handleFolding(playerNr);
		sendPlayerData();
	}
		
	public void prepareNextGame() throws  PlayerCountEx, InvalidPhaseEx, InvalidCardEx, HandSizeEx {
		if(phase != Phase.AnnounceWinner) throw new InvalidPhaseEx();
		if(dcgeddon) {
			sendError("Brak graczy do kolejnej gry!");
			throw new PlayerCountEx();
		}
		theDeck = new Deck();
		phase = Phase.FirstAuction;
		bet = 0;
		hasAllIn = false;
		removeDCed();
		for(int i=0; i<thePlayers.length; i++) {
			thePlayers[i].dropHand();
			for(int j=0; j<5; j++) {
				thePlayers[i].receiveCard(theDeck.takeCard());
			}
		}
		notifyNewGame();
		sendPhaseChange();
		sendData();
	}
	
	public static void payUp (int winnerCount, int players[], Player thePlayers[]) {
		int amount;
		if(winnerCount > 0) {							//kazdy wygrany bierze po kolei od kazdego przegranego haracz
			for(int i=0; i<thePlayers.length; i++) {
				if(players[i] != -1) {
					for(int j=0; j<thePlayers.length; j++) {
						if(players[j] == -1) {
							amount = thePlayers[j].getBet()/winnerCount;
							if(thePlayers[i].hasAllIn() && amount > thePlayers[i].getBet()) {
								amount = thePlayers[i].getBet();
							}
							thePlayers[j].pay(amount);
							thePlayers[i].pay(-amount);
						}
					}
				}
			}
		}
	}
	
	private void sendData() {
		if(pv == null) return;
		PlayerInfo[] pInfo = new PlayerInfo[thePlayers.length];
		int pool = 0;
		for(int i=0; i<thePlayers.length; i++) {
			pInfo[i] = new PlayerInfo();
			pInfo[i].isBot = thePlayers[i].isBot();
			pInfo[i].name = thePlayers[i].getName();
			pInfo[i].bet = thePlayers[i].getBet();
			pInfo[i].tokens = thePlayers[i].getTokens();
			if(thePlayers[i].hasDCed()) {
				pInfo[i].status = "(DC)";
			} else if(thePlayers[i].hasFolded()) {
				pInfo[i].status = "(F)";
			} else if(thePlayers[i].hasAllIn()) {
				pInfo[i].status = "(A)";
			}
			pool += thePlayers[i].getBet();
		}
		int[] cards = new int[5];
		try {
			thePlayers[curPlayer].reportCards(cards);
			pv.showData(pInfo, cards, curPlayer, pool);
			pv.hideCards();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
	
	private void sendPlayerData() {
		if(pv == null) return;
		PlayerInfo[] pInfo = new PlayerInfo[thePlayers.length];
		int pool = 0;
		for(int i=0; i<thePlayers.length; i++) {
			pInfo[i] = new PlayerInfo();
			pInfo[i].isBot = thePlayers[i].isBot();
			pInfo[i].name = thePlayers[i].getName();
			pInfo[i].bet = thePlayers[i].getBet();
			pInfo[i].tokens = thePlayers[i].getTokens();
			if(thePlayers[i].hasDCed()) {
				pInfo[i].status = "(DC)";
			} else if(thePlayers[i].hasFolded()) {
				pInfo[i].status = "(F)";
			} else if(thePlayers[i].hasAllIn()) {
				pInfo[i].status = "(A)";
			}
			pool += thePlayers[i].getBet();
		}
		int[] cards = new int[5];
		try {
			thePlayers[curPlayer].reportCards(cards);
			pv.showData(pInfo, cards, curPlayer, pool);
			pv.redrawCards();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	} 
	
	private void sendPhaseChange() {
		if(pv == null) return;
		pv.setPhase(phase);
	}
	
	private void sendMessage(String msg) {
		if(pv == null) return;
		pv.showMessage(msg);
	}
	
	private void notifyExchangeData() {
		if(pv == null) return;
		PlayerInfo[] pInfo = new PlayerInfo[thePlayers.length];
		int pool = 0;
		for(int i=0; i<thePlayers.length; i++) {
			pInfo[i] = new PlayerInfo();
			pInfo[i].isBot = thePlayers[i].isBot();
			pInfo[i].name = thePlayers[i].getName();
			pInfo[i].bet = thePlayers[i].getBet();
			pInfo[i].tokens = thePlayers[i].getTokens();
			if(thePlayers[i].hasDCed()) {
				pInfo[i].status = "(DC)";
			} else if(thePlayers[i].hasFolded()) {
				pInfo[i].status = "(F)";
			} else if(thePlayers[i].hasAllIn()) {
				pInfo[i].status = "(A)";
			}
			pool += thePlayers[i].getBet();
		}
		int[] cards = new int[5];
		try {
			thePlayers[curPlayer].reportCards(cards);
			pv.receiveExchangerData(pInfo, cards, curPlayer, pool);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
	
	private void notifyNewGame() {
		if(pv == null) return;
		pv.prepareForNextGame(thePlayers.length);
	}
	
	private void sendResults(int[][] cards, WinInfo[] wInfo, String winString) {
		if(pv == null) return;
		pv.showWinners(cards, wInfo, winString);
	}
	
	private void sendError(String e) {
		if(pv == null) return;
		pv.displayError(e);
	}
	
	private void removeDCed() {
		int playCount = 0;
		for(int i=0; i<thePlayers.length; i++) {
			if(!thePlayers[i].hasDCed()) playCount++;
		}
		if(playCount == 0) return;
		Player[] newTable = new Player[playCount];
		playCount = 0;
		for(int i=0; i<thePlayers.length; i++) {
			if(!thePlayers[i].hasDCed()) {
				newTable[playCount] = thePlayers[i];
				playCount++;
			}
		}
		if(opener >= playCount) {
			opener = playCount-1;
			curPlayer = playCount-1;
		}
		thePlayers = newTable;
	}
	
	private void handleFolding(int folder) throws InvalidPhaseEx {
		int foldCount = 0;
		for(int i=0; i<thePlayers.length; i++) {
			if(thePlayers[i].hasFolded()) foldCount++;
		}
		if(foldCount >= thePlayers.length-1) {
			if(++opener >= thePlayers.length) {
				opener = 0;
			}
			curPlayer = opener;
			phase = Phase.AnnounceWinner;
			sendPhaseChange();
			return;
		}
		if(thePlayers[folder].getBet() == bet) {
			bet = 0;
			for(int i=0; i<thePlayers.length; i++) {
				if(!thePlayers[i].hasFolded() && thePlayers[i].getBet() > bet) bet = thePlayers[i].getBet();
			}
		}
		if(folder == curPlayer) {
			incCurPlayer();
		}
	}
	
	private void incCurPlayer() throws InvalidPhaseEx {
		if(phase == Phase.AnnounceWinner) throw new InvalidPhaseEx();
		if(phase == Phase.FirstAuction || phase == Phase.SecondAuction) {
			do {
				if(++curPlayer >= thePlayers.length) {
					curPlayer = 0;
				}
				if(curPlayer == opener) {
					fullCircle = true;
				}
			} while(thePlayers[curPlayer].hasFolded());
			if(bet == 0 || !fullCircle) {
				sendData();
				return;
			}
			for(int i=0; i<thePlayers.length; i++) {
				if(thePlayers[i].getBet() < bet ) {
					if(!thePlayers[i].hasFolded() && !thePlayers[i].hasAllIn())  {
						sendData();
						return;
					}
				}
			}
			if(phase == Phase.FirstAuction) {
				curPlayer = 0;
				while(thePlayers[curPlayer].hasFolded()) {
					curPlayer++;
				}
				phase = Phase.Exchange;
				sendPhaseChange();
				sendData();
				fullCircle = false;
			} else {
				if(++opener >= thePlayers.length) {
					opener = 0;
				}
				curPlayer = opener;
				phase = Phase.AnnounceWinner;
				sendPhaseChange();
				sendData();
				fullCircle = false;
			}
		}
		else if(phase == Phase.Exchange) {
			sendData();
			do {
				if(++curPlayer >= thePlayers.length) {
					if(hasAllIn) {
						if(++opener > thePlayers.length) {
							opener = 0;
						}
						curPlayer = opener;
						phase = Phase.AnnounceWinner;
						sendPhaseChange();
					} else {
						curPlayer = opener;
						while(thePlayers[curPlayer].hasFolded()) {
							curPlayer++;
						}
						phase = Phase.SecondAuction;
						sendPhaseChange();
						notifyExchangeData();
					}
					return;
				}
			} while(thePlayers[curPlayer].hasFolded());
			notifyExchangeData();
		}
	}
	
	/*
	public void play() throws Exception {
		for(int i = 0; i < 5; i++) {
			for(int j = 0; j < thePlayers.length; j++) {
				try {
					thePlayers[j].receiveCard(theDeck.takeCard());
				} catch (InvalidCardEx | HandSizeEx e) {
					// NIEMOŻLIWE //
					throw e;
				}
			}
		}
		
		int counter;
		for(int i = 0; i < thePlayers.length; i++) {
			try {
				thePlayers[i].takeTurn(phase);
			} catch (HandSizeEx e) {
				// NIEMOŻLIWE //
				//System.exit(2);
				throw e;
			}
			counter = thePlayers[i].getHandSize();
			for(int j = 0; j < counter; j++) {
				try {
					thePlayers[i].receiveCard(theDeck.takeCard());
				} catch (InvalidCardEx | HandSizeEx e) {
					//System.exit(3);
					throw e;
				}
			}
			thePlayers[i].endTurn();
		}
		
		int score[][] = new int[thePlayers.length][6];
		int players[] = new int[thePlayers.length];
		int cards[][] = new int[thePlayers.length][5];
		for (int i = 0; i < thePlayers.length; i++) {
			players[i] = i;
			try {
				thePlayers[i].reportCards(cards[i]);
				analyzeCards(score[i], cards[i]);
			} catch (Exception e) {
				//System.exit(4);
				throw e;
			}
		}
		
		for(int i = 0; i < thePlayers.length; i++) {
			thePlayers[i].printCards(i);
		}
		
		try {
			findWinner(score, players);
		} catch (Exception e) {
			//System.exit(5);
			throw e;
		}
		
		int winnerCount = 0;
		for (int i = 0; i < thePlayers.length; i++) {
			if (players[i] != -1) {
				winnerCount++;
			}
		}
		
		if (winnerCount == 1) {
			System.out.print("Wygrał gracz ");
			for (int i = 0; i < thePlayers.length; i++) {
				if (players[i] != -1) {
					System.out.print(i);
				}
			}
			System.out.println("!");
		} else {
			System.out.println("Zremisowali gracze");
			for (int i = 0; i < thePlayers.length; i++) {
				if (players[i] != -1) {
					System.out.println(" " + i);
				}
			}
			System.out.println("!");
		}
	}
	*/
	
	public static int analyzeCards(int report[], int tab[]) {
		boolean color = false, straight = false;
		int three = -1, quad = -1;
		int foundPair[] = { -1, -1 };
		int buffer;
		
		if (tab[0]/13==tab[1]/13 && tab[1]/13==tab[2]/13 && tab[2]/13==tab[3]/13 
			&& tab[3]/13==tab[4]/13) {
			color = true;
		}
		for(int i=0; i<5; i++) {
			tab[i] %= 13;
		}
		for(int i=0; i<5; i++) {
			for(int j=i; j<5; j++) {
				if (i == 0) {
					if (tab[j] > tab[i]) {
						buffer = tab[i];
						tab[i] = tab[j];
						tab[j] = buffer;
					}
				} else if (tab[j] > tab[i] && tab[j] <= tab[i-1]) {
					buffer = tab[i];
					tab[i] = tab[j];
					tab[j] = buffer;
				}	
			}
		}
		
		if (tab[0]==tab[1]+1 && tab[1]==tab[2]+1 && tab[2]==tab[3]+1 
			&& tab[3]==tab[4]+1) {
			straight = true;
		}
		
		for(int i=0; i<4; i++) {
			if(tab[i]==tab[i+1] && tab[i]!=foundPair[0]) {
				if(i < 2 && tab[i+2]==tab[i+3] && tab[i+2]==tab[i]) {
					quad = tab[i];
				}
				if(foundPair[0] == -1) { foundPair[0] = tab[i]; } 
				else foundPair[1] = tab[i];
			}
			if(i < 3 && tab[i]==tab[i+1] && tab[i+1]==tab[i+2]) {
				three = tab[i];
			}
		}
		
		if (color && straight) { 
			report[0] = 9;
			report[1] = tab[0];
		} else if (quad != -1) {
			report[0] = 8;
			report[1] = quad;
		} else if (three != -1 && (foundPair[0]!=three || foundPair[1]!=-1)) {
			report[0] = 7;
			report[1] = three;
		} else if (color) {
			report[0] = 6;
			for(int i=0; i<5; i++) {
				report[i+1] = tab[i];
			}
		} else if (straight) {
			report[0] = 5;
			report[1] = tab[0];
		} else if (three != -1) {
			report[0] = 4;
			report[1] = three;
		} else if (foundPair[0]!=-1 && foundPair[1] != -1) {
			report[0] = 3;
			if(foundPair[0] > foundPair[1]) {
				report[1] = foundPair[0];
				report[2] = foundPair[1];
			} else {
				report[1] = foundPair[1];
				report[2] = foundPair[0];
			}
			for(int i=0; i<5; i++) {
				if (tab[i] != foundPair[0] && tab[i] != foundPair[1]) {
					report[3] = tab[i];
					break;
				}
			}
		} else if (foundPair[0] != -1) {
			report[0] = 2;
			report[1] = foundPair[0];
			for(int i=2; i<5; i++) {
				for(int j=0; j<5; j++) {
					if (i == 2) {
						if (tab[j] != foundPair[0] && tab[j] > report[i]) {
							report[i] = tab[j]; 
						}
					} else if (tab[j] != foundPair[0] && tab[j] > report[i] && tab[j] < report[i-1]) {
						report[i] = tab[j];
					}	
				}
			}
		} else {
			report[0] = 1;
			for(int i=0; i<5; i++) {
				report[i+1] = tab[i];
			}
		}
		
		return 0;
	}
	
	public static void findWinner(int score[][], int players[]) throws IllegalArgumentException {
		int l =  players.length;
		for (int i = 0; i < l; i++) {
			if (players[i] > l-1 || players[i] < -1) {
				throw new IllegalArgumentException();
			}
		}

		int max = 0;

		for (int i = 0; i < 6; i++) {
			for (int j = 0; j < l; j++) {
				if (players[j] != -1) {
					if (score[players[j]][i] > max) {
						max = score[players[j]][i];
					}
				}
			}

			for (int j = 0; j < l; j++) {
				if (players[j] != -1) {
					if (score[players[j]][i] != max) {
						players[j] = -1;
					}
				}
			}

			max = 0;
		}
	}
}
